package bd403.namespace.test;

import java.security.SecureRandom;

import junit.framework.Assert;

import com.jayway.android.robotium.solo.Solo;
import bd403.Backend.Login;
import bd403.UIComponents.AddActiv;
import bd403.UIComponents.AddReviewActiv;
import bd403.UIComponents.DrinkViewActiv;
import bd403.UIComponents.HelpActiv;
import bd403.UIComponents.SearchActiv;
import bd403.namespace.BDActivity;
import android.test.ActivityInstrumentationTestCase2;

/* UI Testing of the BrewDawg application
 * Main authors: Cody Bentosino and Brendan Emler */

public class UITesting extends ActivityInstrumentationTestCase2<Login> {
	private static SecureRandom r = new SecureRandom();
	private static String letters = "abcdefghijklmnopqrstuvwxyz"; 
	private static String testDrink = createString("Testdrink L");
	private Solo solo;
	
	public UITesting() {
		super("bd403.Backend", Login.class);
	}
	
	public void setUp() throws Exception {
		solo = new Solo(getInstrumentation(), getActivity());		
	}
	
	/* private helper method that logs in with the given user and pw */
	private void login(String user, String pw) {
		solo.enterText(0, user);
		solo.enterText(1, pw);
		solo.clickOnButton("Login");
		solo.assertCurrentActivity("Should have loaded BDActivity", BDActivity.class);
	}
	
	/* private helper method that generates a random string */
	private static String createString(String base) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < 10; i++) {
			sb.append(letters.charAt(r.nextInt(26)));
		}
		return base += sb.toString();
	}
	
	/* Tests registering a new user 
	 * Expected result: successful registration and user should be on the home page
	 * Black-box */
	public void testRegistration() {
		String testUser = createString("testUser");
		solo.clickOnText("Register Here");
		solo.sleep(3000);
		solo.enterText(0, testUser);
		solo.enterText(1, "password");
		solo.enterText(2, "password");
		solo.clickOnCheckBox(0);
		solo.clickOnButton("Register New Account");
		solo.sleep(3000);
		solo.assertCurrentActivity("Should be on the home page", BDActivity.class);
	}
	
	/* Tests an invalid username and password
	 * Expected result: user is not able to log in and should still be on the login page
	 * Black-box
	 */
	public void testInvalidLogin() {
		solo.enterText(0, "invalidUser");
		solo.enterText(1, "password");
		solo.clickOnButton("Login");
		solo.assertCurrentActivity("Should still be on the login page", Login.class);
	}
	
	/* Tests clicking on the Help tab
	 * Expected result: user should be on the Help tab
	 * Black-box
	 */
	public void testHelpTab() {
		login("c", "b");
		solo.clickOnMenuItem("Help");
		solo.assertCurrentActivity("Should be on the Help screen", HelpActiv.class);
		solo.goBack();		
	}
	
	/* Tests clicking on the Add tab
	 * Expected result: user should be on the Add tab
	 * Black-box
	 */
	public void testAddTab() {
		login("c", "b");
		solo.clickOnText("Add");
		solo.assertCurrentActivity("Should be on the Add tab", AddActiv.class);
		Assert.assertTrue(solo.searchText("+ Add Drink"));
	}
	
	/* Tests clicking on the Search tab
	 * Expected result: user should be on the Search tab
	 * Black-box
	 */
	public void testSearchTab() {
		login("c", "b");
		solo.clickOnText("Search");
		solo.assertCurrentActivity("Should be on the Search tab", SearchActiv.class);		
	}
	
	/* Tests the add functionality of the app
	 * Expected result: successfully adds a drink with 5 stars and a comment; user ends up on the drink view page
	 * Black-box
	 */
	public void testAddDrink() {
		login("b", "e");
		solo.clickOnText("Add");
		solo.enterText(0, testDrink);
		solo.clickOnRadioButton(2);
		solo.setProgressBar(0, 5);
		solo.enterText(1, "Nothing compares to this!");
		solo.clickOnButton(3);
		solo.assertCurrentActivity("Should be on DrinkViewActiv", DrinkViewActiv.class);
		Assert.assertTrue(solo.searchText(testDrink));
	}
	
	/* Tests adding a review to an existing drink
	 * Expected result: adds a review of 0 stars and a comment to 'testDrink'
	 * Black-box
	 */
	public void testAddReview() throws Throwable {
		login("c", "b");
		solo.clickOnText("Search");
		solo.enterText(0, testDrink);
		solo.clickOnButton(0);
		solo.clearEditText(0);
		solo.clickOnText(testDrink);
		solo.assertCurrentActivity("Should be on Review page", DrinkViewActiv.class);
		
		solo.clickOnButton(0);
		solo.assertCurrentActivity("Should be on Add Review page", AddReviewActiv.class);
		
		solo.setProgressBar(0, 0);
		solo.enterText(0, "Something compares to this!");
		solo.clickOnButton(0);
		Assert.assertTrue(solo.searchText("Something compares to this!"));
	}
	
	/*
	 * Tests adding a drink to favorites. This test logs in, searches for a drink,
	 * then adds it to favorites.
	 * 
	 * Expected result: the user adds to favorites and the drink shows up in favorites
	 * tab. Blackbox
	 */
	public void testAddToFavorites() {
		// Register user
		String testUser = createString("testUser");
		solo.clickOnText("Register Here");
		solo.sleep(3000);
		solo.enterText(0, testUser);
		solo.enterText(1, "password");
		solo.enterText(2, "password");
		solo.clickOnCheckBox(0);
		solo.clickOnButton("Register New Account");
		solo.sleep(3000);
		
		// Find the test drink
		solo.clickOnText("Search");
		solo.enterText(0, testDrink);
		solo.clickOnButton(0);
		solo.clearEditText(0);
		solo.clickOnText(testDrink);
		
		// click on "+ Favorites"
		solo.clickOnButton(1);
		solo.goBack();
		
		solo.clickOnText("Home");
		
		//click on "Your Favorites" button
		solo.clickOnRadioButton(1);
		
		// Drink that was just favorited should be in favorites list
		Assert.assertTrue(solo.searchText(testDrink));
	}
	
	/* method that restarts the application at the end of each test call */
	public void tearDown() throws Exception {
		solo.finishOpenedActivities();
	}	
}